//
//  DataConvert.swift
//  KoiAccounting
//
//  Created by 纪洪文 on 20.03.25.
//

import Foundation

extension Date {
    
    func previousWeek() -> Date {
        var calendar = Calendar.current
        calendar.firstWeekday = 2 // Set Monday as the first day of the week
        return calendar.date(byAdding: .weekOfYear, value: -1, to: self)!
    }
    
    func nextWeek() -> Date {
        var calendar = Calendar.current
        calendar.firstWeekday = 2 // Set Monday as the first day of the week
        return calendar.date(byAdding: .weekOfYear, value: 1, to: self)!
    }
    
    func previousMonth() -> Date {
        let calendar = Calendar.current
        return calendar.date(byAdding: .month, value: -1, to: self)!
    }
    
    func nextMonth() -> Date {
        let calendar = Calendar.current
        return calendar.date(byAdding: .month, value: 1, to: self)!
    }
    
    func previousYear() -> Date {
        let calendar = Calendar.current
        return calendar.date(byAdding: .year, value: -1, to: self)!
    }
    
    func nextYear() -> Date {
        let calendar = Calendar.current
        return calendar.date(byAdding: .year, value: 1, to: self)!
    }
    
    func toISODateString() -> String {
        let dateformatter = ISO8601DateFormatter()
        // dateformatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
        return dateformatter.string(from: self)
    }
    
    func toWeek() -> String {
        var calendar = Calendar.current
        calendar.firstWeekday = 2 // Set Monday as the first day of the week

        let currentYear = calendar.component(.year, from: Date())
        let dateYear = calendar.component(.year, from: self)
        let isThisYear = dateYear == currentYear
        
        let dateFormatter = DateFormatter()
        if (isThisYear) {
            dateFormatter.dateFormat = "MM/dd"
        } else {
            dateFormatter.dateFormat = "yyyy/MM/dd"
        }
        var components = calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
        components.weekday = 2  // 2 表示周一
        
        // 计算本周的周一和周日的日期
        let startOfWeek = calendar.date(from: components)!
        let endOfWeek = calendar.date(byAdding: .day, value: 6, to: startOfWeek)!
        
        let startText = dateFormatter.string(from: startOfWeek)
        let endText = dateFormatter.string(from: endOfWeek)
        
        return "\(startText)~\(endText)"
    }
    
    func toYearMonth() -> String {
        let dateformatter = DateFormatter()
        dateformatter.dateFormat = "yyyy-MM"
        return dateformatter.string(from: self)
    }
    
    func toYear() -> String {
        let dateformatter = DateFormatter()
        dateformatter.dateFormat = "yyyy"
        return dateformatter.string(from: self)
    }
    
    func toYearMonthDay() -> String {
        let dateformatter = DateFormatter()
        dateformatter.dateFormat = "yyyy/MM/dd"
        return dateformatter.string(from: self)
    }
    
    func toWeekDays() -> Array<String> {
        var calendar = Calendar.current
        if let chinaTimeZone = TimeZone(identifier: "Asia/Shanghai") {
            calendar.timeZone = chinaTimeZone
        } else {
            print("Failed to set China time zone. Using current time zone.")
        }
        calendar.firstWeekday = 2 // Set Monday as the first day of the week

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"

        let startOfWeek = calendar.date(from: calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))!
        var dates: [String] = []
        
        for i in 0..<7 {
            if let date = calendar.date(byAdding: .day, value: i, to: startOfWeek) {
                let dateStr = dateFormatter.string(from: date)
                dates.append(dateStr)
            }
        }
        return dates
    }
    
    // 月最大天数
    func monthMaxDays() -> Int {
        let calendar = Calendar.current
        let range = calendar.range(of: .day, in: .month, for: self)
        return range!.count
    }
    
    // 当前月的全部日期
    func monthDays() -> [String] {
        var dates = [String]()
        let calendar = Calendar.current
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        // 获取当前月的范围
        let range = calendar.range(of: .day, in: .month, for: self)!
        // 获取当前月的第一个日期
        var components = calendar.dateComponents([.year, .month], from: self)
        components.day = 1
        let firstDateOfMonth = calendar.date(from: components)!
        // 遍历当前月的所有日期
        for day in range {
            if let date = calendar.date(byAdding: .day, value: day - 1, to: firstDateOfMonth) {
                dates.append(dateFormatter.string(from: date))
            }
        }
        return dates
    }
    
    func yearMonths() -> [String] {
        let calendar = Calendar.current
        let year = calendar.component(.year, from: self)
        return (1...12).map {
            if $0 < 10 {
                "\(year)-0\($0)"
            } else {
                "\(year)-\($0)"
            }
        }
    }
    
    func dayOfWeek() -> Int {
        var calendar = Calendar.current
        calendar.firstWeekday = 2 // Set Monday as the first day of the week
        let weekday = calendar.component(.weekday, from: self)
        // Calculate the day of the week with Monday as the first day
        let dayOfWeek = (weekday + 5) % 7 + 1
        return dayOfWeek
    }
    
    func dayOfMonth() -> Int {
        let calendar = Calendar.current
        return calendar.component(.day, from: self)
    }
    
    func monthOfYear() -> Int {
        let calendar = Calendar.current
        return calendar.component(.day, from: self)
    }
    
    /// 将日期转换为友好的显示格式
    func toFriendlyString(withTime: Bool = false) -> String {
        let calendar = Calendar.current
        
        // 去除时间部分，只比较日期
        let dateToCompare = calendar.startOfDay(for: self)
        
        if calendar.isDateInToday(dateToCompare) {
            return "今天" + (withTime ? timeString : "")
        }
        
        if calendar.isDateInYesterday(dateToCompare) {
            return "昨天" + (withTime ? timeString : "")
        }
        
        // 如果是明天
        if calendar.isDateInTomorrow(dateToCompare) {
            return "明天" + (withTime ? timeString : "")
        }
        
        // 其他日期使用标准格式
        return withTime
            ? DateFormatter.fullDateTimeFormatter.string(from: self)
            : DateFormatter.friendlyDateFormatter.string(from: self)
    }
    
    /// 获取时间部分字符串
    private var timeString: String {
        let formatter = DateFormatter()
        formatter.dateFormat = " HH:mm"
        return formatter.string(from: self)
    }
    
    /// 获取星期几字符串
    var weekdayString: String {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "zh_CN")
        return formatter.weekdaySymbols[Calendar.current.component(.weekday, from: self) - 1]
    }
    
    /// 判断日期是否在本周内
    private var isInCurrentWeek: Bool {
        let calendar = Calendar.current
        let currentWeek = calendar.component(.weekOfYear, from: Date())
        let dateWeek = calendar.component(.weekOfYear, from: self)
        return currentWeek == dateWeek
    }
}

extension String {
    
    func toDate() -> Date? {
        let dateformatter = ISO8601DateFormatter()
        let isoDate = dateformatter.date(from: self)
        if isoDate == nil {
            let date = DateFormatter.isoDateFormatter.date(from: self)
            return date ?? Date()
        } else {
            return isoDate!
        }
    }
}

extension DateFormatter {
    /// 友好的日期格式化工具，支持"今天"、"昨天"和标准日期格式
    static let friendlyDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy/MM/dd"
        formatter.locale = Locale(identifier: "zh_CN")
        formatter.calendar = Calendar.current
        return formatter
    }()
    
    /// 完整的日期时间格式化工具
    static let fullDateTimeFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy/MM/dd HH:mm"
        formatter.locale = Locale(identifier: "zh_CN")
        formatter.calendar = Calendar.current
        return formatter
    }()
    
    /// 完整的日期时间格式化工具
    static let isoDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
        return formatter
    }()
}

struct DateUtils {
    
    static func date(year: Int, month: Int, day: Int = 1) -> Date {
        var components = DateComponents()
        components.year = year
        components.month = month
        components.day = day
        return Calendar.current.date(from: components) ?? Date()
    }
    
    static func inThisWeek(weekDays: Array<String>, date:Date = Date()) -> Bool {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        return weekDays.contains(dateFormatter.string(from: date))
    }
    
    static func inThisMonth(data: Date, currentData:Date = Date()) -> Bool {
        let calendar = Calendar.current
        let currentMonth = calendar.component(.month, from: currentData)
        let currentYear = calendar.component(.year, from: currentData)
        
        let month = calendar.component(.month, from: data)
        let year = calendar.component(.year, from: data)
        return currentYear == year && currentMonth == month
    }
    
    static func inThisYear(data: Date, currentData:Date = Date()) -> Bool {
        let calendar = Calendar.current
        let currentYear = calendar.component(.year, from: currentData)
        let year = calendar.component(.year, from: data)
        return currentYear == year
    }
    
    static func dayOfWeek(date: Date) -> Int? {
        var calendar = Calendar.current
        calendar.firstWeekday = 2 // Set Monday as the first day of the week
        
        let weekday = calendar.component(.weekday, from: date)
        
        // Calculate the day of the week with Monday as the first day
        let dayOfWeek = (weekday + 5) % 7 + 1
        
        return dayOfWeek
    }
    
    static func weekdaySymbols(from dateString: String, format: String = "yyyy-MM-dd") -> String? {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = format
        guard let date = dateFormatter.date(from: dateString) else {
            return nil
        }
        return date.weekdayString
    }
    
    static func monthDayAbbr(from dateString: String, format: String = "yyyy-MM-dd") -> String? {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = format
        guard let date = dateFormatter.date(from: dateString) else {
            return nil
        }
        return String(date.dayOfMonth())
    }
    
    static func weekdayAbbr(from dateString: String, format: String = "yyyy-MM-dd") -> String? {
        switch DateUtils.weekdaySymbols(from: dateString, format: format) {
        case "星期一":
            return "周一"
        case "星期二":
            return "周二"
        case "星期三":
            return "周三"
        case "星期四":
            return "周四"
        case "星期五":
            return "周五"
        case "星期六":
            return "周六"
        case "星期日":
            return "周日"
        default:
            return ""
        }
    }
}
